package com.geek.water.controller;

import com.geek.water.constant.CodeConstant;
import com.geek.water.constant.InvoiceConstants;
import com.geek.water.constant.MessageConstant;
import com.geek.water.dto.InvoiceQueryDTO;
import com.geek.water.dto.InvoiceRequestDTO;
import com.geek.water.dto.InvoiceResponseDTO;
import com.geek.water.entity.Bill;
import com.geek.water.entity.Invoice;
import com.geek.water.result.Result;
import com.geek.water.service.BillService;
import com.geek.water.service.InvoiceService;
import com.geek.water.service.NuonuoInvoiceService;
import com.geek.water.utils.NumberToChinese;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@RestController
@RequestMapping(value = "/admin/invoice", produces = "application/json;charset=UTF-8")
@RequiredArgsConstructor
@Api(tags = "水务发票服务接口")
public class InvoiceController {

    private final NuonuoInvoiceService nuonuoInvoiceService;
    private final InvoiceService invoiceService;
    private final BillService billService;

    /**
     * 标准开票接口 - 支持前端调用
     */
    @PostMapping("applyByBill")
    @ApiOperation("申请开具发票")
    public Result applyByBill(
            @RequestParam String billCode,
            @RequestParam String buyerName,
            @RequestParam(required = false) String buyerTaxCode,
            @RequestParam(required = false) String buyerAddressPhone,
            @RequestParam(required = false) String buyerBankAccount,
            @RequestParam(required = false) String remark,
            @RequestParam(required = false) String checkCode,
            @RequestParam(required = false) String machineCode,
            @RequestParam(required = false, defaultValue = "增值税普通发票") String type,
            @RequestParam(required = false) String receiptor,
            @RequestParam(required = false) String issuer,
            @RequestParam(required = false) String reviewer,
            @RequestParam(required = false) String goodsName,
            @RequestParam(required = false, defaultValue = "1") String quantity,
            @RequestParam(required = false, defaultValue = "吨") String unit,
            @RequestParam(required = false, defaultValue = "0.06") String taxRate
    ) {
        try {
            log.info("申请开具发票，账单编号：{}，购方名称：{}", billCode, buyerName);

            // 参数验证
            if (!StringUtils.hasLength(billCode) || !StringUtils.hasLength(buyerName)) {
                return new Result(CodeConstant.FAIL, "账单编号和购方名称不能为空");
            }

            // 通过billCode获取账单信息
            Bill bill = billService.findByBillCode(billCode);
            if (bill == null) {
                return new Result(CodeConstant.FAIL, "账单不存在");
            }

            // 检查账单是否已开票
            if (bill.getInvoiced() != null && bill.getInvoiced() == 1) {
                return new Result(CodeConstant.FAIL, "该账单已开具发票");
            }

            // 检查账单金额是否有效
            if (bill.getAmount() == null || bill.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                return new Result(CodeConstant.FAIL, "账单金额必须大于0");
            }

            // 检查数量是否有效
            BigDecimal quantityDecimal;
            try {
                quantityDecimal = new BigDecimal(quantity);
                if (quantityDecimal.compareTo(BigDecimal.ZERO) <= 0) {
                    return new Result(CodeConstant.FAIL, "商品数量必须大于0");
                }
            } catch (NumberFormatException e) {
                return new Result(CodeConstant.FAIL, "商品数量格式不正确");
            }

            // 构建发票明细
            InvoiceRequestDTO.InvoiceDetailDTO detail = new InvoiceRequestDTO.InvoiceDetailDTO();
            detail.setTaxRate(taxRate);
            detail.setInvoiceLineProperty("0");
            detail.setSelfCode("服务");
            detail.setListName("企业");
            detail.setSpecType("水费缴费");
            detail.setGoodsName(goodsName != null ? goodsName : "水费");
            detail.setGoodsCode("3040801");
            detail.setWithTaxFlag("1");
            detail.setNum(quantity);
            detail.setTax(""); // 自动计算
            detail.setUnit(unit);
            detail.setDeduction("0");

            // 修正金额计算：使用账单金额作为不含税金额
            BigDecimal unitPrice = bill.getAmount().divide(quantityDecimal, 2, RoundingMode.HALF_UP);
            detail.setPrice(unitPrice.toString());
            detail.setTaxExcludedAmount(bill.getAmount().toString());

            List<InvoiceRequestDTO.InvoiceDetailDTO> details = new ArrayList<>();
            details.add(detail);

            // 构建请求DTO
            InvoiceRequestDTO requestDTO = new InvoiceRequestDTO();
            requestDTO.setBillcode(billCode);
            requestDTO.setBuyerName(buyerName);
            requestDTO.setBuyerAddress(buyerAddressPhone != null ? buyerAddressPhone : "");
            requestDTO.setBuyerTaxNum(buyerTaxCode != null ? buyerTaxCode : "");
            requestDTO.setBuyerPhone(buyerAddressPhone != null ? buyerAddressPhone : "");
            requestDTO.setEmail("");
            requestDTO.setInvoiceDetail(details);

            // 调用服务申请开票
            InvoiceResponseDTO response = nuonuoInvoiceService.applyInvoice(requestDTO);

            // 格式化当前日期为字符串
            String currentDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

            if (InvoiceConstants.APPLY_SUCCESS_CODE.equals(response.getCode())) {
                // 申请成功，创建发票对象
                Invoice invoice = new Invoice();

                // 设置基础信息
                invoice.setBillCode(billCode);
                invoice.setInvoiceCode(response.getData() != null ? response.getData().getInvoiceCode() : "");

                // 设置购方信息
                invoice.setBuyerName(buyerName);
                invoice.setBuyerTaxCode(buyerTaxCode);
                invoice.setBuyerAddressPhone(buyerAddressPhone);
                invoice.setBuyerBankAccount(buyerBankAccount);

                // 设置销方信息 - 使用常量
                invoice.setSellerName(InvoiceConstants.TEST_SALER_NAME);
                invoice.setSellerTaxCode(InvoiceConstants.TEST_SALER_TAX_NUM);
                invoice.setSellerAddressPhone(InvoiceConstants.TEST_SALER_ADDRESS);
                invoice.setSellerBankAccount(InvoiceConstants.TEST_SALER_ACCOUNT);

                // 设置金额信息
                invoice.setAmountInFiguers(bill.getAmount());
                invoice.setAmountInWords(convertAmountToWords(bill.getAmount().toString()));

                // 设置其他信息
                invoice.setType(type);
                invoice.setReceiptor(receiptor);
                invoice.setIssuer(issuer);
                invoice.setReviewer(reviewer);
                invoice.setRemark(remark);
                invoice.setCheckCode(checkCode);
                invoice.setMachineCode(machineCode);
                invoice.setInvoiceDate(LocalDate.parse(currentDate));

                // 立即查询完整发票信息（诺诺网开票是异步的）
                InvoiceResponseDTO queryResponse = null;
                int retryCount = 3;

                // 构建查询参数
                InvoiceQueryDTO queryDTO = new InvoiceQueryDTO();
                queryDTO.setBillcode(billCode);
                queryDTO.setInvoiceCode(invoice.getInvoiceCode());

                // 重试机制获取完整发票信息
                while (retryCount > 0) {
                    try {
                        queryResponse = nuonuoInvoiceService.queryInvoice(queryDTO);

                        if (queryResponse != null &&
                                InvoiceConstants.APPLY_SUCCESS_CODE.equals(queryResponse.getCode()) &&
                                queryResponse.getData() != null &&
                                !ObjectUtils.isEmpty(queryResponse.getData().getImgUrls())) {
                            break; // 成功获取到完整信息
                        }

                        // 等待2秒后重试
                        Thread.sleep(2000);
                        retryCount--;
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        log.warn("发票查询被中断", e);
                    } catch (Exception e) {
                        log.error("发票查询异常，重试中...", e);
                        retryCount--;
                    }
                }

                // 使用查询结果更新发票信息
                if (queryResponse != null &&
                        InvoiceConstants.APPLY_SUCCESS_CODE.equals(queryResponse.getCode()) &&
                        queryResponse.getData() != null) {

                    InvoiceResponseDTO.InvoiceDataDTO data = queryResponse.getData();

                    // 更新发票关键信息
                    invoice.setInvoiceNumber(data.getInvoiceNumber());
                    invoice.setCheckCode(data.getCheckCode());
                    invoice.setMachineCode(data.getMachineCode());
                    invoice.setAmountInFiguers(new BigDecimal(data.getTotalAmount()));
                    invoice.setInvoiceUrl(data.getImgUrls());
                    invoice.setStatus(data.getStatus());

                    // 处理开票日期
                    if (data.getInvoiceDate() != null && !data.getInvoiceDate().isEmpty()) {
                        try {
                            long timestamp = Long.parseLong(data.getInvoiceDate());
                            invoice.setInvoiceDate(java.time.Instant.ofEpochMilli(timestamp)
                                    .atZone(java.time.ZoneId.systemDefault())
                                    .toLocalDate());
                        } catch (NumberFormatException e) {
                            log.warn("日期格式转换失败: {}", data.getInvoiceDate(), e);
                        }
                    }
                }

                // 保存发票记录
                boolean saved = invoiceService.save(invoice);
                if (saved) {
                    // 更新账单开票状态
                    updateBillInvoiceStatus(billCode, true);
                    return new Result(CodeConstant.SUCCESS, MessageConstant.INVOICE_APPLY_SUCCESS, invoice);
                } else {
                    return new Result(CodeConstant.FAIL, "发票申请成功但保存失败");
                }
            } else {
                // 申请失败处理 - 不保存到数据库，只返回错误信息
                log.error("发票申请失败，账单编号：{}，错误信息：{}", billCode, response.getMessage());
                return new Result(CodeConstant.FAIL, response.getMessage() != null ? response.getMessage() : MessageConstant.INVOICE_APPLY_FAIL);
            }
        } catch (Exception e) {
            log.error("申请开具发票失败", e);
            return new Result(CodeConstant.FAIL, MessageConstant.INVOICE_APPLY_FAIL + "：" + e.getMessage());
        }
    }

    /**
     * 将金额转换为中文大写
     */
    private String convertAmountToWords(String amount) {
        try {
            double num = Double.parseDouble(amount);
            return NumberToChinese.convert(String.valueOf(num));
        } catch (Exception e) {
            log.warn("金额转换失败: {}", amount, e);
            return "";
        }
    }

    /**
     * 更新账单开票状态
     */
    private void updateBillInvoiceStatus(String billCode, boolean invoiced) {
        try {
            Bill bill = billService.findByBillCode(billCode);
            if (bill != null) {
                bill.setInvoiced(invoiced ? 1 : 0);
                billService.updateById(bill);
            }
        } catch (Exception e) {
            log.error("更新账单开票状态失败，账单编号：{}", billCode, e);
        }
    }

    @GetMapping("/query")
    @ApiOperation("查询发票状态")
    public Result queryInvoice(
            @RequestParam String billCode,
            @RequestParam(required = false) String invoiceCode,
            @RequestParam(required = false) String invoiceNumber) {
        try {
            // 先通过billCode查找账单
            Bill bill = billService.findByBillCode(billCode);
            if (bill == null) {
                return new Result(CodeConstant.FAIL, "账单不存在");
            }

            // 优先查询本地数据库
            Invoice local = invoiceService.findByBillCode(billCode);
            if (local != null && local.getInvoiceCode() != null && local.getInvoiceUrl() != null) {
                // 如果传入了invoiceCode，需要验证是否匹配
                if (StringUtils.hasLength(invoiceCode) && !invoiceCode.equals(local.getInvoiceCode())) {
                    return new Result(CodeConstant.FAIL, "发票代码不匹配，请检查输入");
                }
                return new Result(CodeConstant.SUCCESS, "本地发票信息", local);
            }

            // 如果本地没有完整数据，则查询诺诺网
            InvoiceQueryDTO q = new InvoiceQueryDTO();
            q.setBillcode(billCode);
            q.setInvoiceCode(invoiceCode);
            q.setInvoiceNumber(invoiceNumber);
            InvoiceResponseDTO resp = nuonuoInvoiceService.queryInvoice(q);

            if (InvoiceConstants.APPLY_SUCCESS_CODE.equals(resp.getCode()) && resp.getData() != null) {
                InvoiceResponseDTO.InvoiceDataDTO d3 = resp.getData();

                // 如果本地有记录但信息不完整，则更新本地记录
                if (local != null) {
                    // 只更新诺诺网返回的字段，保留本地其他信息
                    local.setInvoiceCode(d3.getInvoiceCode());
                    local.setInvoiceNumber(d3.getInvoiceNumber());
                    local.setCheckCode(d3.getCheckCode());
                    local.setMachineCode(d3.getMachineCode());

                    String date3 = d3.getInvoiceDate();
                    if (date3 != null && !date3.isEmpty()) {
                        try {
                            long ts2 = Long.parseLong(date3);
                            local.setInvoiceDate(java.time.Instant.ofEpochMilli(ts2).atZone(java.time.ZoneId.systemDefault()).toLocalDate());
                        } catch (NumberFormatException e) {
                            log.warn("日期格式转换失败: {}", date3, e);
                        }
                    }

                    local.setAmountInFiguers(new BigDecimal(d3.getTotalAmount()));
                    local.setAmountInWords(convertAmountToWords(d3.getTotalAmount()));
                    local.setInvoiceUrl(d3.getImgUrls());
                    local.setStatus(d3.getStatus());

                    invoiceService.updateById(local);
                    return new Result(CodeConstant.SUCCESS, "发票查询成功", local);
                } else {
                    // 如果本地没有记录，创建新记录（但信息可能不完整）
                    Invoice inv = new Invoice();
                    inv.setBillCode(billCode);
                    inv.setInvoiceCode(d3.getInvoiceCode());
                    inv.setInvoiceNumber(d3.getInvoiceNumber());
                    inv.setCheckCode(d3.getCheckCode());
                    inv.setMachineCode(d3.getMachineCode());

                    String date3 = d3.getInvoiceDate();
                    if (date3 != null && !date3.isEmpty()) {
                        try {
                            long ts2 = Long.parseLong(date3);
                            inv.setInvoiceDate(java.time.Instant.ofEpochMilli(ts2).atZone(java.time.ZoneId.systemDefault()).toLocalDate());
                        } catch (NumberFormatException e) {
                            log.warn("日期格式转换失败: {}", date3, e);
                        }
                    }

                    inv.setAmountInFiguers(new BigDecimal(d3.getTotalAmount()));
                    inv.setAmountInWords(convertAmountToWords(d3.getTotalAmount()));
                    inv.setInvoiceUrl(d3.getImgUrls());
                    inv.setStatus(d3.getStatus());

                    // 设置默认的销方信息（因为诺诺网查询不返回这些信息）
                    inv.setSellerName(InvoiceConstants.TEST_SALER_NAME);
                    inv.setSellerTaxCode(InvoiceConstants.TEST_SALER_TAX_NUM);
                    inv.setSellerAddressPhone(InvoiceConstants.TEST_SALER_ADDRESS);
                    inv.setSellerBankAccount(InvoiceConstants.TEST_SALER_ACCOUNT);
                    inv.setType("增值税普通发票");

                    invoiceService.save(inv);
                    return new Result(CodeConstant.SUCCESS, "发票查询成功", inv);
                }
            } else {
                return new Result(CodeConstant.FAIL, "发票查询失败: " + resp.getMessage());
            }
        } catch (Exception e) {
            log.error("发票查询异常", e);
            return new Result(CodeConstant.FAIL, "系统错误: " + e.getMessage());
        }
    }
}